package com.zj.pojo.vo;

import java.io.Serializable;
import java.util.List;
import java.util.Map;
import lombok.AllArgsConstructor;
import lombok.Getter;
import lombok.ToString;
import org.elasticsearch.common.recycler.Recycler.V;
import org.springframework.lang.NonNull;
import org.springframework.lang.Nullable;

/**
 * <p>统一返回结果集<p/>
 *
 * @author 赵赳
 * @since 2021/9/17 14:10
 */
@Getter
@ToString
@AllArgsConstructor
public class FinalResultVO<T> implements Serializable {

  @NonNull
  private final Boolean success;

  @NonNull
  private final String code;

  @NonNull
  private final String msg;

  private final T data;

  // ok without data
  private static final FinalResultVO<Void> OK = new FinalResultVO<>(
      true,
      RespStatusEnum.OK.getCode(),
      RespStatusEnum.OK.getMsg(),
      null);

  // fail without data
  private static final FinalResultVO<Void> FAIL = new FinalResultVO<>(
      false,
      RespStatusEnum.INTERNAL_SERVICE_ERROR.getCode(),
      RespStatusEnum.INTERNAL_SERVICE_ERROR.getMsg(),
      null);

  public static FinalResultVO<Void> ok() {
    return OK;
  }

  public static FinalResultVO<Void> fail() {
    return FAIL;
  }

  /**
   * 输入data
   *
   * @param data object类型参数
   * @param <T>  泛型
   * @return ok
   */
  @NonNull
  public static <T> FinalResultVO<T> ok(@Nullable T data) {
    return ok(data, RespStatusEnum.OK.getMsg());
  }

  @NonNull
  public static <T> FinalResultVO<T> ok(
      @Nullable T data, @NonNull String msg
  ) {
    return new FinalResultVO<>(
        true,
        RespStatusEnum.OK.getCode(),
        msg,
        data);
  }

  @NonNull
  public static FinalResultVO<Void> ok(@NonNull String msg) {
    return new FinalResultVO<>(true, RespStatusEnum.OK.getCode(), msg, null);
  }

  @NonNull
  public static <T> FinalResultVO<List<T>> ok(@NonNull List<T> data) {
    return ok(data, RespStatusEnum.OK.getMsg());
  }

  @NonNull
  public static <T> FinalResultVO<List<T>> ok(
      @NonNull List<T> data, @NonNull String msg
  ) {
    return new FinalResultVO<>(true, RespStatusEnum.OK.getCode(), msg, data);
  }

  @NonNull
  public static <T> FinalResultVO<T> fail(@NonNull RespStatusEnum status) {
    return fail(null, status, status.getMsg());
  }

  @NonNull
  public static <T> FinalResultVO<T> fail(@NonNull String msg) {
    return fail(null, RespStatusEnum.INTERNAL_SERVICE_ERROR, msg);
  }

  @NonNull
  public static <T> FinalResultVO<T> fail(@NonNull RespStatusEnum status, @NonNull String msg) {
    return fail(null, status, msg);
  }


  @NonNull
  public static <T> FinalResultVO<T> fail(
      @Nullable T data, @NonNull RespStatusEnum status, @NonNull String msg
  ) {
    if (RespStatusEnum.OK == status) {
      throw new IllegalArgumentException("FinalResult#fail() 方法不可以传 RespStatusEnum#OK 状态");
    }
    return new FinalResultVO<>(false, status.getCode(), msg, data);
  }


}
